#include "BoundingVolume.h"
#include <math.h>
gewAabb::gewAabb():
	minVertex(0,0,0),
	maxVertex(0,0,0),
	outerPlane(0)
{}
	gewAabb::gewAabb( gewVec3 _minVertex,
						gewVec3 _maxVertex):
	minVertex(_minVertex),
	maxVertex(_maxVertex),
	outerPlane(0)
{}
gewAabb::gewAabb( float minX,
			float minY,
			float minZ,
			float maxX,
			float maxY,
			float maxZ ):
	minVertex(minX,minY,minZ),
	maxVertex(maxX,maxY,maxZ),
	outerPlane(0)
{}
gewAabb::~gewAabb()
{}
void gewAabb::repair()
{
	if( minVertex.x>maxVertex.x )
	{
		float	temp = minVertex.x;
		minVertex.x = maxVertex.x;
		maxVertex.x = temp;
	}
	if( minVertex.y>maxVertex.y )
	{
		float	temp = minVertex.y;
		minVertex.y = maxVertex.y;
		maxVertex.y = temp;
	}
	if( minVertex.z>maxVertex.z )
	{
		float	temp = minVertex.z;
		minVertex.z = maxVertex.z;
		maxVertex.z = temp;
	}
}
void gewAabb::addInternalPoint(float x, 
							float y, 
							float z)
{
	if (x>maxVertex.x) maxVertex.setX(x);
	if (y>maxVertex.y) maxVertex.setY(y);
	if (z>maxVertex.z) maxVertex.setZ(z);

	if (x<minVertex.x) minVertex.setX(x);
	if (y<minVertex.y) minVertex.setY(y);
	if (z<minVertex.z) minVertex.setZ(z);
}
void gewAabb::addInternalPoint(gewVec3& point)
{
	float x = point.getX();
	float y = point.getY();
	float z = point.getZ();
	if (x>maxVertex.getX()) 
		maxVertex.setX(x);
	if (y>maxVertex.getY()) 
		maxVertex.setY(y);
	if (z>maxVertex.getZ()) 
		maxVertex.setZ(z);

	if (x<minVertex.getX()) 
		minVertex.setX(x);
	if (y<minVertex.getY()) 
		minVertex.setY(y);
	if (z<minVertex.getZ()) 
		minVertex.setZ(z);
}
void gewAabb::addInternalBox(gewAabb& inner_box)
{
	addInternalPoint( inner_box.minVertex.getX(),
										inner_box.minVertex.getY(),
										inner_box.minVertex.getZ() );
	addInternalPoint( inner_box.maxVertex.getX(),
										inner_box.maxVertex.getY(),
										inner_box.maxVertex.getZ() );
}
//				_________
//			 /|7 	    /|6
//			/ |			 / |					^ y
//		4/__|___ 5/	 |					|
//		|   |		  |	 |					|
//		|   |_____|__|1         |----> x
//		|	 /0		 	|  /				 /
//		| /				| /					/
//		|/3_______|2				 < z
//
//void gewAabb::getVertexList(vector_t* vertex_array) const
//{
//	//vertex 0
//	//vertex_array[0].setX( minVertex.getX());
//	//vertex_array[0].setY( minVertex.getY());
//	//vertex_array[0].setZ( minVertex.getZ());
//	////vertex 1
//	//vertex_array[1].setX( maxVertex.getX());
//	//vertex_array[1].setY( minVertex.getY());
//	//vertex_array[1].setZ( minVertex.getZ());
//	////vertex 2
//	//vertex_array[2].setX( maxVertex.getX());
//	//vertex_array[2].setY( minVertex.getY());
//	//vertex_array[2].setZ( maxVertex.getZ());
//	////vertex 3
//	//vertex_array[3].setX( minVertex.getX());
//	//vertex_array[3].setY( minVertex.getY());
//	//vertex_array[3].setZ( maxVertex.getZ());
//	////vertex 4
//	//vertex_array[4].setX( minVertex.getX());
//	//vertex_array[4].setY( maxVertex.getY());
//	//vertex_array[4].setZ( maxVertex.getZ());
//	////vertex 5
//	//vertex_array[5].setX( maxVertex.getX());
//	//vertex_array[5].setY( maxVertex.getY());
//	//vertex_array[5].setZ( maxVertex.getZ());
//	////vertex 6
//	//vertex_array[6].setX( maxVertex.getX());
//	//vertex_array[6].setY( maxVertex.getY());
//	//vertex_array[6].setZ( minVertex.getZ());
//	////vertex 7
//	//vertex_array[7].setX( minVertex.getX());
//	//vertex_array[7].setY( maxVertex.getY());
//	//vertex_array[7].setZ( minVertex.getZ());
//}
//E_INTERSECTION Aabb::isContain(vector_t& p)
//{
//	if( p.getX() >= minVertex.getX() && p.getX() <= maxVertex.getX() &&
//			p.getY() >= minVertex.getY() && p.getY() <= maxVertex.getY() &&
//			p.getZ() >= minVertex.getZ() && p.getZ() <= maxVertex.getZ() )
//		return EI_IN;
//	else
//		return EI_OUT;				
//}
//E_INTERSECTION Aabb::isContain(Aabb& _box)
//{
//	E_INTERSECTION test1 = testTwoValueRange( minVertex.getX(), maxVertex.getX(),
//																						_box.minVertex.getX(), _box.maxVertex.getX() );
//	E_INTERSECTION test2 = testTwoValueRange( minVertex.getY(), maxVertex.getY(),
//																						_box.minVertex.getY(), _box.maxVertex.getY() );
//	E_INTERSECTION test3 = testTwoValueRange( minVertex.getZ(), maxVertex.getZ(),
//																						_box.minVertex.getZ(), _box.maxVertex.getZ() );
//	if( test1 == EI_OUT || test2 == EI_OUT || test3 == EI_OUT )
//		return EI_OUT;
//	if( test1 == EI_IN && test2 == EI_IN && test3 == EI_IN )
//		return EI_IN;
//	if( test1 == EI_INTERNAL && test2 == EI_INTERNAL && test3 == EI_INTERNAL )
//		return EI_INTERNAL;
//	return EI_INTERSECT;																						
//}
//E_INTERSECTION Aabb::isIntersectionWithLineSegment( const vector_t point1,
//																										const vector_t point2,
//																										vector_t& intersect1,
//																										vector_t& intersect2) const
//{
//	return EI_OUT;
//}
bool gewAabb::isValid()
{
	return true;
	//return maxVertex>minVertex;
}


gewSphere::gewSphere():
	center(0,0,0),
	radius(1),
	outerPlane(0)
{}
gewSphere::gewSphere(gewVec3 _center, float _radius):
	center(_center),
	radius(_radius),
	outerPlane(0)
{}

gewSphere::gewSphere(gewAabb &box)
{
	center	= ( box.minVertex+box.maxVertex ) /2;
	radius	=	( center- box.minVertex ).getLength();
	outerPlane = box.outerPlane;
}
void gewSphere::addInternalPoint(float x, 
							  float y, 
							  float z)
{
	gewVec3 temp;
	gewVec3 d(x,y,z);
	// vector dc = center - vector d
	gewVec3 dc = center - d;
	// Check point d outside the sphere
	if( dc.getLength() > (radius+ 0.01) )
	{
		dc.normalize();
		temp = (center +  dc*radius + d)/2;
		center = temp;
		radius = ( d - center).getLength(); 
	}
}
void gewSphere::addInternalPoint(gewVec3& d)
{
	gewVec3 temp;
	// vector dc = center - vector d
	gewVec3 dc = center - d;
	// Check point d outside the sphere
	if( dc.getLength() > (radius+ 0.01) )
	{
		dc.normalize();
		temp = (center +  dc*radius + d)/2;
		center = temp;
		radius = ( d - center).getLength(); 
	}
}
//void gewSphere::addInternalSphere(gewSphere& _sphere)
//{
//	int test = isContain( _sphere );
//	if(test == EI_IN )
//		return;
//	if(test == EI_INTERNAL )
//	{
//		center = _sphere.center;
//		radius = _sphere.radius;
//	}																	
//	// Vector center-> _sphere.center
//	vector_t c1c2_n		=  (_sphere.center - center).normalize();
//	// Find the farthest point with this sphere that on _sphere
//	vector_t farthest_point = _sphere.center + c1c2_n* _sphere.radius;
//	addInternalPoint(farthest_point);
//}
void gewSphere::calculate(float *vertex_list,int num)
{
	// find center
	center= gewVec3(0,0,0);
	int count=0;
	for (int i=0;i<num;i+=3) 
	{
		center+= gewVec3(vertex_list[i],vertex_list[i+1],vertex_list[i+2]);
		count++;
	}
	center/= float(count);
	// find farthest point in set
	radius=0.0f;
	for (int i=0;i<num;i+=3) 
	{
	   gewVec3 d = gewVec3(vertex_list[i],vertex_list[i+1],vertex_list[i+2]) - center;
	   float dist = d.getLengthSquare();
	   if (dist>radius)
			radius=dist;
	}
	radius=sqrtf(radius);
}
void gewSphere::calculate(arrayVec3 vertices)
{
	// find center
	center= gewVec3(0,0,0);
	int count=0;
	for (int i=0;i< vertices.size();i++)
	{
		center+= vertices[i];
		count++;
	}
	center/= float(count);
	// find farthest point in set
	radius=0.0f;
	for (int i=0;i< vertices.size();i++) 
	{
		gewVec3 d = vertices[i] - center;
	   float dist = d.getLengthSquare();
	   if (dist>radius)
			radius=dist;
	}
	radius=sqrtf(radius);
}

//E_INTERSECTION Sphere::isContain(vector_t& p)
//{
//	if( (p- center).getLengthSquare() > (radius*radius) )
//		return EI_OUT;
//	else
//		return EI_IN;				
//}
//E_INTERSECTION Sphere::isContain(Sphere& _sphere)
//{
//	float_t d = (center - _sphere.center).getLength();
//	if( d > ( radius + _sphere.radius ) )
//		return EI_OUT;
//	if( d < radius ) 
//		return EI_IN;
//	if( d < _sphere.radius )
//		return EI_INTERNAL;
//	
//	return EI_INTERSECT;
//}